package com.ahm.service;

import com.ahm.pojo.Product;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Future;

/**
 * 商品管理
 */
@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 查询商品列表
     *
     * @return
     */
//    @Cacheable(cacheNames = "orderService:product:list")
    @Override
    @HystrixCommand(groupKey = "order-productService-listPool",// 服务名称，相同名称使用同一个线程池
            commandKey = "selectProductList", // 接口名称，默认为方法名
            threadPoolKey = "order-productService-listPool", // 线程池名称，相同名称使用同一个线程池
            commandProperties = {
                    // 超时时间，默认 1000ms
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
                            value = "5000")
            },
            threadPoolProperties = {
                    // 线程池大小
                    @HystrixProperty(name = "coreSize", value = "6"),
                    // 队列等待阈值(最大队列长度，默认 -1)
                    @HystrixProperty(name = "maxQueueSize", value = "100"),
                    // 线程存活时间，默认 1min
                    @HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
                    // 超出队列等待阈值执行拒绝策略
                    @HystrixProperty(name = "queueSizeRejectionThreshold", value = "100")
            },fallbackMethod = "selectProductListFallback") // 拖地数据
    public List<Product> selectProductList() {
        System.out.println(Thread.currentThread().getName() + "-----selectProductList-----");
        // ResponseEntity: 封装了返回数据
        return restTemplate.exchange(
                "http://product-service/product/list", HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<Product>>() {
                }).getBody();
    }
    // 托底数据
    private List<Product> selectProductListFallback() {
        System.out.println("-----selectProductListFallback-----");
        return Arrays.asList(
                new Product(1, "托底数据-华为手机", 1, 5800D),
                new Product(2, "托底数据-联想笔记本", 1, 6888D),
                new Product(3, "托底数据-小米平板", 5, 2020D)
        );
    }



    /**
     * 根据多个主键查询商品
     *
     * @param ids
     * @return
     */
    @HystrixCollapser(batchMethod = "selectProductListByIds", // 合并请求方法
            scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL, // 请求方式
            collapserProperties = {
                    // 间隔多久的请求会进行合并，默认 10ms
                    @HystrixProperty(name = "timerDelayInMilliseconds", value = "20"),
                    // 批处理之前，批处理中允许的最大请求数
                    @HystrixProperty(name = "maxRequestsInBatch", value = "200")

            })
    @Override
    @HystrixCommand(commandProperties = {
            // 超时时间，默认 1000ms
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
                    value = "5000")
    })
    public List<Product> selectProductListByIds(List<Integer> ids) {
        StringBuffer sb = new StringBuffer();
        ids.forEach(id -> sb.append("id=" + id + "&"));
        return restTemplate.getForObject("http://product-service/product/listByIds?" + sb.toString(), List.class);
    }

    /**
     * 根据主键查询商品
     *
     * @param id
     * @return
     */
    @Override
//    @Cacheable(cacheNames = "orderService:product:single", key = "#id")
    @HystrixCollapser(batchMethod = "selectProductListByIds", // 合并请求方法
            scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL, // 请求方式
            collapserProperties = {
                    // 间隔多久的请求会进行合并，默认 10ms
                    @HystrixProperty(name = "timerDelayInMilliseconds", value = "20"),
                    // 批处理之前，批处理中允许的最大请求数
                    @HystrixProperty(name = "maxRequestsInBatch", value = "200")
            })
    public Future<Product> selectProductById(Integer id) {
        System.out.println("-----orderService-----selectProductById-----");
        return null;
    }

}